
package podcastbyphone.server;

import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import podcastbyphone.client.Podcast;
import podcastbyphone.client.PodcastMap;
import podcastbyphone.server.TwilioProperties;


import rss.*;
import twilio.markup.Gather;
import twilio.markup.Play;
import twilio.servlet.TwilioRequest;
import twilio.client.DialStatus;
import twilio.client.SmsStatus;


public class TwilioPodcastServlet
	extends twilio.servlet.TwilioServlet
{
	private static final Logger log =
			                    Logger.getLogger( TwilioPodcastServlet.class.getName() );

	private static final String LISTEN_TO_NPR_NEWS_SUMMARY = "1";
	private static final String LISTEN_TO_NPR_TECHNOLOGY = "2";
	private static final String LISTEN_TO_NPR_MUSIC = "3";
	private static final String LISTEN_TO_NPR_SCIENCE_FRIDAY = "4";
	private static final String LISTEN_TO_NPR_PLANET_MONEY = "5";
	private static final String LISTEN_TO_THIS_AMERICAN_LIFE = "6";
	private static final String LISTEN_TO_THINK_OUT_LOUD = "7";
	
	private static final int ONE_MINUTE = 60;
	private static final int TWO_MINUTES = 2 * (ONE_MINUTE);
	private static final int ONE_HOUR = (60 * ONE_MINUTE);
	private static final int TWO_HOURS = (2 * ONE_HOUR);
	
	@Override
	protected void onDialCallback(TwilioRequest req, DialStatus dialStatus)
	{
		log.info("onDialCallback");
		pause(1);
		say("Good bye");
		hangup();
	}

	
	
	@Override
	protected void onGatherCallback(TwilioRequest req, String digits)
	{
		log.info("onGatherCallback: " + digits);
		
		Podcast podcast = null;
		
		char c = digits.charAt(0);
		
		if (Character.isDigit(c))
		{
			Integer digit = new Integer("" + c);
			
			log.info("digit=" + digit);
			
			podcast = getPodcastMap().get(digit);
		}
		
		
		if (podcast != null)
		{
			
			log.info("user selected podcast: " + podcast.getDescription());
			log.info("podcast base url: " + podcast.getUrl());
			
			try
			{
				RSS rss = RSS.loadFromUrl(podcast.getUrl());
				
				Item item = rss.getFirstItem();
				
				if ( (item != null) && (item.getEnclosure() != null))
				{
					Enclosure enc = item.getEnclosure();
					Gather g = new Gather();
					g.add(new Play(enc.getUrl()));
					g.setAction(getHttpServletRequest().getRequestURL());
					g.setFinishOnKey(null);
					g.setNumDigits(1);
					
					log.log(Level.INFO, "duration: " + item.getDuration());
					log.log(Level.INFO, "duration in seconds: " + item.getDurationInSeconds());
					
					if (item.getDurationInSeconds() != null)
					{
						g.setTimeout(item.getDurationInSeconds());
					}
					else
					{
						g.setTimeout( TWO_MINUTES );
					}
					
					add(g);
						
					redirect();
				}
				else
				{
					say("Pod cast error");
					log.log(Level.WARNING, "enclosure is null?");
					redirect();
				}
			}
			catch (Exception ex)
			{
				say("System error");
				log.log(Level.WARNING, "exception", ex);
				redirect();
			}
		}
		else
		{
			redirect();
		}
	}



	@Override
	protected void onInboundCall(TwilioRequest req, String caller, String called)
	{
		log.info("onInboundCall");
		
		for (int i = 0; i < 2; i++)
		{
			PodcastMap pmap = getPodcastMap();
			
			String[] msgs = new String[pmap.size()];
			
			Iterator<Integer> iterKeys = pmap.keySet().iterator();
			
			for (int z = 0; z < msgs.length; z++)
			{
				Integer key = iterKeys.next();
				Podcast p = pmap.get(key);
				msgs[z] = "Press " + key + " to listen to " + p.getDescription(); 
			}
			
			gather(1, 15, msgs);
			
		}
		
		say("Good bye");
		hangup();
		
	}


	@Override
	protected void onRecordCallback(TwilioRequest req, String recordingUrl)
	{
		log.info("Record callback");
	}



	@Override
	protected void onTranscribeCallback(TwilioRequest req,
			twilio.client.TranscriptionStatus status, 
			String text)
	{
		log.info("Transcribe callback: " + text);
	}


	@Override
	protected String getTwilioAccountPhoneNumber()
	{
		return TwilioProperties.getAccountPhoneNumber();
	}


	@Override
	protected String getTwilioAuthToken()
	{
		return TwilioProperties.getTwilioAuthToken();
	}

	
	@Override
	protected boolean verifyRequest(TwilioRequest req)
	{
		return true;
	}

	private PodcastMap getPodcastMap()
	{
		return new PodcastMap();
	}



	@Override
	protected void onSmsReceived(TwilioRequest req, String smsSid, String from,
			String to, String messageBody)
	{
		String outboundFrom = to;
		String outboundTo = from;
		String outboundMsg = "echo:" + messageBody.trim();
		
		sms(outboundFrom, outboundTo, outboundMsg);
		
	}



	@Override
	protected void onSmsStatus(TwilioRequest req, String smsSid,
			SmsStatus smsStatus)
	{
		log.info("got SMS status: " + smsStatus);
	}

	@Override
	protected void onCallCompleted(TwilioRequest req)
	{
		if (req.getCaller() != null)
		{
			sms(this.getTwilioAccountPhoneNumber(), req.getCaller(), "Source code available:  http://code.google.com/p/podcastbyphone");
		}
	}

}
